Skip to content

MOB-52691: prototype remote Streamable HTTP transport (spike) - #35

Draft
dylan-white-bc wants to merge 1 commit into
masterfrom
mob-52691-remote-mcp-streamable-http
Draft

MOB-52691: prototype remote Streamable HTTP transport (spike)#35
dylan-white-bc wants to merge 1 commit into
masterfrom
mob-52691-remote-mcp-streamable-http

Conversation

@dylan-white-bc

Copy link
Copy Markdown

Summary

Adds an opt-in Streamable HTTP transport so the API Monitoring MCP server can run as a
remote endpoint, while leaving local stdio behavior unchanged.

Epic: MOB-52691 — [API-MCP] Cloud-hosted API Monitoring MCP server (Streamable HTTP)
Spike: MOB-53088 — Spike: Support for Remote Http MCP server

Transport

  • --mcp http or BZM_API_TEST_MCP_TRANSPORT=http selects Streamable HTTP; stdio remains the default.
  • Endpoint served at /mcp (configurable via FASTMCP_STREAMABLE_HTTP_PATH), with /health and /healthz probes for load-balancer checks.
  • stateless_http=True — the tools hold no cross-request state, so no MCP session store is needed and restarts do not invalidate clients.

Authentication

  • Hosted mode resolves the API Monitoring token per request from the Authorization header; it never falls back to a server-wide token.
  • stdio mode continues to use its startup token.
  • HTTP requests without a well-formed Bearer credential are rejected with 401 before any tool executes.
  • Requests carrying an Origin header are rejected — browser/CORS support is intentionally out of scope for this prototype.

Note

This is pass-through auth — the caller's token is forwarded to the API Monitoring APIs.
The MCP specification treats this as an anti-pattern,
so separate MCP authentication remains an open question for MOB-52691.

Adds an opt-in Streamable HTTP transport so the API Monitoring MCP server
can run as a remote endpoint, while leaving local stdio behavior unchanged.

Transport:
- `--mcp http` or BZM_API_TEST_MCP_TRANSPORT=http selects Streamable HTTP;
  stdio remains the default.
- Endpoint served at /mcp (configurable), with /health and /healthz probes
  for load-balancer checks.
- stateless_http=True: the tools hold no cross-request state, so no MCP
  session store is needed and restarts do not invalidate clients.

Authentication:
- Hosted mode resolves the API Monitoring token per request from the
  Authorization header; it never falls back to a server-wide token.
- stdio mode continues to use its startup token.
- HTTP requests without a well-formed Bearer credential are rejected with
  401 before any tool executes.
- Requests carrying an Origin header are rejected (browser/CORS support is
  intentionally out of scope for this prototype).

Note: this is pass-through auth -- the caller's token is forwarded to the
API Monitoring APIs. The MCP specification treats this as an anti-pattern,
so separate MCP authentication remains an open question for the epic.

Tests: 150 passing, including request-scoped credential isolation and a
regression test asserting the outgoing Authorization header carries the raw
credential (BzmApimToken.__repr__ masks itself, so a non-string token would
silently send a masked header).

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in Streamable HTTP transport path to run this MCP server as a remote HTTP endpoint, while keeping the default local stdio transport. This introduces request-scoped token resolution for hosted mode plus a basic HTTP security boundary (no browser Origin, Bearer required except health checks).

Changes:

  • Add transport selection (stdio default, opt-in http) and server construction logic, with Streamable HTTP hosted serving via Uvicorn.
  • Introduce hosted-mode auth/security primitives (TokenResolver, HttpSecurityMiddleware, /health + /healthz) and update tool registration to use request-scoped tokens.
  • Add tests covering transport resolution, hosted-vs-stdio credential behavior, and HTTP middleware behavior; document Streamable HTTP hosting in the README.

Reviewed changes

Copilot reviewed 14 out of 14 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/test_main_transport.py Adds unit tests for CLI/env transport resolution and correct server startup behavior per transport.
tests/test_http_security.py Adds tests for HTTP middleware behavior (Bearer required, Origin rejected, health unauthenticated).
tests/test_auth.py Adds tests for request-scoped vs startup token resolution and that the resolved credential reaches API calls.
src/tools/test_manager.py Switches tool registration to resolve token per request via TokenResolver.
src/tools/team_manager.py Switches tool registration to resolve token per request via TokenResolver.
src/tools/step_manager.py Switches tool registration to resolve token per request via TokenResolver.
src/tools/schedule_manager.py Switches tool registration to resolve token per request via TokenResolver.
src/tools/result_manager.py Switches tool registration to resolve token per request via TokenResolver.
src/tools/environment_manager.py Switches tool registration to resolve token per request via TokenResolver.
src/tools/bucket_manager.py Switches tool registration to resolve token per request via TokenResolver.
src/server.py Threads hosted-mode flag through tool registration and centralizes token resolution via TokenResolver.
src/config/auth.py Adds request token parsing, token resolver, HTTP security middleware, health routes, and Streamable HTTP runner.
README.md Documents how to run and configure the Streamable HTTP hosted endpoint and its auth/security expectations.
main.py Adds transport selection/CLI changes, builds server for stdio vs HTTP, and runs Streamable HTTP when selected.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread main.py
host=host,
port=port,
streamable_http_path=os.getenv("FASTMCP_STREAMABLE_HTTP_PATH", "/mcp").strip() or "/mcp",
stateless_http=True,
Comment thread src/config/auth.py
Comment on lines +1 to +6
import anyio
import uvicorn
from mcp.server.fastmcp import Context, FastMCP
from starlette.requests import Request
from starlette.responses import JSONResponse
from starlette.types import ASGIApp, Receive, Scope, Send
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants